package cn.security.auth;

import jdk.nashorn.internal.runtime.logging.Logger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@SpringBootApplication(scanBasePackages={"cn.security.auth"})
//@MapperScan("cn.club.mapper")
@Slf4j
public class SpringSecurityDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringSecurityDemoApplication.class, args);
        log.info("============认证服务============");
        log.info("============认证服务============");
        log.info("============认证服务============");
    }

    static {
        // todo:认证流程
        // 过滤器一：提交用户名密码
        /**
         * 流程一：提交用户名密码
         * {@link UsernamePasswordAuthenticationFilter}
         */
        // UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter = new UsernamePasswordAuthenticationFilter();

        /** 流程二：构建Authentication接口的认证对象UsernamePasswordAuthenticationToken
         * {@link org.springframework.security.authentication.UsernamePasswordAuthenticationToken}
         */

        /**
         * 流程三：接口AuthenticationManager的实现类ProviderManager的authenticate()进行认证
         * {@link org.springframework.security.authentication.ProviderManager#authenticate(Authentication)}
         */

        /**
         * 流程四: 调用DaoAuthenticationProvider的authenticate()进行认证
         * {@link org.springframework.security.authentication.dao.DaoAuthenticationProvider#authenticate(Authentication)}
         */

        /**
         * 流程五: 调用DaoAuthenticationProvider类的retrieveUser方法中的loadUserByUsername方法查询用户信息
         *
         * {@link org.springframework.security.authentication.dao.DaoAuthenticationProvider#retrieveUser(String, UsernamePasswordAuthenticationToken)}
         */

        /**
         * todo:自定义替换从数据库查询用户信息 实现 UserDetailsService 接口
         * 流程六: 默认调用InMemoryUserDetailsManager#loadUserByUsername方法查询[用户信息、权限信息]封装成UserDetails对象
         * {@link org.springframework.security.provisioning.InMemoryUserDetailsManager#loadUserByUsername(String)}
         * return {@link org.springframework.security.provisioning.MutableUser}
         */

        /**
         * 流程七: 调用DaoAuthenticationProvider类的additionalAuthenticationChecks方法进行密码校验
         * {@link org.springframework.security.authentication.dao.DaoAuthenticationProvider#additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken)}
         */

        /**
         * 流程八: 密码正确，认证成功后，AbstractUserDetailsAuthenticationProvider 返回一个Authentication认证接口的实现类 UsernamePasswordAuthenticationToken
         * {@link org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider#createSuccessAuthentication(Object, Authentication, UserDetails)}
         */

        /**
         * 流程九: 将返回的Authentication认证对象, 保存到上下文对象中，其他的过滤器会通过SecurityContextHolder获取用户信息
         * {@link SecurityContextHolder#getContext()#setAuthentication()}
         */
    }
}
